﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;

namespace Assets.Editor.BehaviorEditor.View
{
    public class Node
    {
        public Func<Node, List<Node>> GetBrotherNodes;

        private Vector2 size = new Vector2(150, 40);

        public Rect rect;
        private GUIStyle style;
        private GUIStyle nodeStyle;
        private GUIStyle selectedStyle;
        private string title;
        public string Title
        {
            get { return title; }
            set { title = value; }
        }

        private int id;
        public int Id
        {
            get { return id; }
            set { id = value; }
        }

        private bool isDrag;
        private bool isSelected;

        private ConnectionPoint inPoint;

        public ConnectionPoint InPoint
        {
            get { return inPoint; }
        }

        private ConnectionPoint outPoint;
        public ConnectionPoint OutPoint
        {
            get { return outPoint; }
        }

        public Vector2 Position
        {
            get { return rect.position; }
        }

        private bool isRoot;

        public bool IsRoot
        {
            get { return isRoot; }
        }

        private Action<Node> removeNodeClick;

        public Node(
            Vector2 position
            , Action<ConnectionPoint> inPointClick
            , Action<ConnectionPoint> outPointClick
            , Action<Node> removeNodeClick
            , Func<Node, List<Node>> getBrotherNodes
            , bool displayInPoint = true
            , bool displayOutPoint = true)
        {
            Init(position
                , inPointClick
                , outPointClick
                , removeNodeClick
                , getBrotherNodes
                , displayInPoint
                , displayOutPoint);
        }

        private void Init(Vector2 position
            , Action<ConnectionPoint> inPointClick
            , Action<ConnectionPoint> outPointClick
            , Action<Node> removeNodeClick
            , Func<Node, List<Node>> getBrotherNodes
            , bool displayInPoint
            , bool displayOutPoint)
        {
            rect = new Rect(position, size);
            style = nodeStyle = (GUIStyle)"flow node 1";
            selectedStyle = (GUIStyle)"flow node 1 on";

            if(displayInPoint)
            {
                inPoint = new ConnectionPoint(this, ConnectionPointType.In, inPointClick);
            }
            if(displayOutPoint)
            {
                outPoint = new ConnectionPoint(this, ConnectionPointType.Out, outPointClick);
            }

            this.removeNodeClick = removeNodeClick;
            this.GetBrotherNodes = getBrotherNodes;
        }

        public void Draw()
        {
            GUI.Box(rect, title, style);
            if (inPoint != null) inPoint.Draw();
            if (outPoint != null) outPoint.Draw();
        }

        public void ProcessEvent(Event e)
        {
            switch (e.type)
            {
                case EventType.MouseDown:
                    if (e.button == 0)
                    {
                        if (rect.Contains(e.mousePosition))
                        {
                            style = selectedStyle;
                            isSelected = true;
                            isDrag = true;
                        }
                        else
                        {
                            style = nodeStyle;
                            isSelected = false;
                        }
                        GUI.changed = true;
                    }

                    if (e.button == 1
                        && isSelected
                        && rect.Contains(e.mousePosition)
                        && !isRoot)
                    {
                        ProcessMenu();
                        e.Use();
                    }
                    break;
                case EventType.MouseUp:
                    isDrag = false;
                    break;
                case EventType.MouseDrag:
                    if (isDrag)
                    {
                        Drag(e.delta);
                        GUI.changed = true;
                        e.Use();
                    }
                    break;
            }
        }

        private void ProcessMenu()
        {
            GenericMenu menu = new GenericMenu();
            menu.AddItem(new GUIContent("编辑数据"), false, EditNodeData);
            menu.AddItem(new GUIContent("删除节点"), false, RemoveNodeClick);
            menu.ShowAsContext();
        }

        private void EditNodeData()
        {
            //TODO 打开节点编辑窗口
        }

        private void RemoveNodeClick()
        {
            removeNodeClick(this);
        }

        public void Drag(Vector2 delta)
        {
            rect.position += delta;
        }
    }
}
